import random
import time
from functools import lru_cache

from pydantic import BaseSettings
from queue import Queue
import time

no_use_queue = Queue()

# dotenv_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), '.fastenv')
# if os.path.exists(dotenv_path):
#     load_dotenv(dotenv_path, override=True)  # override=True: 覆写已存在的变量
#
# dotenv_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), '.env')
# if os.path.exists(dotenv_path):
#     load_dotenv(dotenv_path, override=True)  # override=True: 覆写已存在的变量
# from rearq import ReArq
from run_set_redis import get_url_list


class Settings(BaseSettings):
    app_name: str = "cjserver API"
    SQLALCHEMY_DATABASE_URI_2: str
    SQLALCHEMY_DATABASE_URI_3: str
    VERSION: str
    MYSQL_HOST_1: str
    MYSQL_PORT_1: int
    MYSQL_USER_1: str
    MYSQL_PWD_1: str
    MYSQL_DATEBASE_1: str
    MONGODB_URI_HTMLSBD: str
    MONGODB_URI_HTMLSBD_DB: str
    MONGODB_URI_HTMLSBDLATEST: str
    MONGODB_URI_HTMLSBDLATEST_DB: str
    MONGODB_URI_OVERSEA_SBDLATEST: str
    MONGODB_URI_HOVERSEA_SBDLATEST_DB: str
    REDIS: str
    PROXY_URL: str
    QINGTING_PROXY_URL: str
    TAIYANG_REDIS_PROXY_URL: str
    TAIYANG_REDIS_PROXY_URL_OBJ: str
    TAIYANG_REDIS_PROXY_URL_OBJ_QINGTING: str
    CHAOXING_PROXY_URL: str
    UPDATE_TASK: str
    CHAOXING_COOKIE_GET: str
    PARA_URL: str
    SQL_ADD_URL: str
    SQL_ADD_MANY_URL: str
    SQL_UPDATE_URL: str
    SQL_UPDATE_LIST_URL: str
    MONGO_SAVE_URL: str
    MONGO_SAVE_ETL_URL: str
    SELECT_URL: str
    RESET_NEW_DATA_URL: str
    DEL_MONGO_ERR: str
    MONGO_BASE_DIR: str
    MONGO_SAVE_PATH: str
    MONGO_SAVE_MAX_SIZE: int
    MONGO_SAVE_TRY_CNT: int
    DB3_EXPORT_URL: str
    ETL_LOCAL_DO_URL: str
    ETL_LOCAL_DO_BATCH_URL: str
    ETL_LOCAL_DO_BATCH_REF_URL: str
    ETL_LOCAL_VALIDATE_URL: str
    ETL_REMOTE_META_URL: str
    ETL_REMOTE_META_BATCH_URL: str
    GET_INFO_DEBUG: str
    ETL_REMOTE_REF_URL: str
    ETL_REMOTE_REF_BATCH_URL: str
    ETL_REMOTE_FULLTEXT_BATCH_URL: str
    SDB_LISTS: str
    SDB_CONN: str
    SDB_USE_IP: str
    CHAOXING_DB3: str
    SUBJECT_LIST: str
    SUBJECT_MAP: str
    CNKI_DB3: str
    WANFANG_DB3: str
    MDB_EXPORT_URL: str
    CHAOXING_MDB: str
    CNKI_MDB: str
    WANFANG_MDB: str
    CHAOXING_ISSUE_HTML: str
    AWS_LOCAL_ACCESS_KEY_ID: str
    AWS_LOCAL_SECRET_ACCESS_KEY: str
    AWS_LOCAL_ENDPOINT_URL: str
    AWS_LOCAL_BUCKET: str
    MINIO_GT_16M_DIR: str
    SCHOOL_PROXY_URL: str
    ZDAYE_PROXY_URL: str

    class Config:
        env_file = ".env"

    # @classmethod
    # def get_info_debug(cls):
    #     if Settings.GET_INFO_DEBUG == "true":
    #         return True
    #     else:
    #         return False
    #
    # @classmethod
    # def get_sdb_lists(cls):
    #     return eval(Settings.SDB_LISTS)
    #
    # @classmethod
    # def get_sdb_conn(cls):
    #     return eval(Settings.SDB_CONN)


@lru_cache()
def get_settings():
    return Settings()


class BaseUrlQueue(object):
    pass


class URLDISTRIBUTED(object):

    @classmethod
    async def get_weight_url(cls):
        """
        获取权重url 处理任务
        :return:
        """

    @classmethod
    async def get_base_url(cls, tag="main"):
        """
        获取随机url 处理任务
        :return:
        """
        from app_main import app
        if app.state.tags.find("test") > -1:
            return "http://127.0.0.1:" + str(app.state.port)
        queue_name = tag + "_queue_url"
        if hasattr(BaseUrlQueue, queue_name):
            queue = eval("BaseUrlQueue." + queue_name)
        else:
            # 在exec 中 两个等于将类赋值给两个变量无效 及 a = b = C() 中只有 a对象有效
            exec("BaseUrlQueue." + queue_name + " = Queue()")
            queue = eval("BaseUrlQueue." + queue_name)

        time_tag_name = tag + "_time_up"
        if hasattr(BaseUrlQueue, time_tag_name):
            time_up = eval("BaseUrlQueue." + time_tag_name)
            if time.time() - time_up > 60:
                try:
                    while True:
                        queue.get_nowait()
                except:
                    print("get_global_baseurl 清理队列完成")

        try:
            url = queue.get_nowait()
        except:
            print("get_global_baseurl 队列空了")
            # 获取redis 全部url

            redis = app.state.redis
            url_list = await redis.smembers("baseurl")
            list_url = get_url_list(tag, url_list)
            if list_url is None or list_url == []:
                return "http://127.0.0.1:8001"
            exec("BaseUrlQueue." + time_tag_name + " = time.time()")
            for i in list_url:
                queue.put(i)
            try:
                url = queue.get_nowait()
            except:
                return "http://127.0.0.1:8001"

        return "http://" + url

    @classmethod
    async def get_base_url_back(cls):
        """
        获取随机url 处理任务
        :return:
        """
        from app_main import app
        redis = app.state.redis
        url = await redis.srandmember("baseurl")
        if app.state.tags.find("test") > -1:
            return "http://127.0.0.1:" + str(app.state.port)
        else:
            if url:
                return url
            else:
                return "http://127.0.0.1:8001"

    @classmethod
    async def get_redis_proxy_one(cls):
        url = await cls.get_base_url()
        url = url + get_settings().TAIYANG_REDIS_PROXY_URL
        return url

    @classmethod
    async def get_qingting_proxy_one(cls):
        url = await cls.get_base_url()
        url = url + get_settings().QINGTING_PROXY_URL
        return url

    @classmethod
    async def get_school_proxy_one(cls):
        url = await cls.get_base_url()
        url = url + get_settings().SCHOOL_PROXY_URL
        return url


    @classmethod
    async def get_zdaye_proxy_one(cls):
        url = await cls.get_base_url()
        url = url + get_settings().ZDAYE_PROXY_URL
        return url

    @classmethod
    async def get_para_url(cls):
        # url_list = [
        #     "192.168.31.202:8004",
        #     "192.168.31.202:8003",
        #     "192.168.31.202:8002",
        #     "192.168.31.164:8004",
        #     "192.168.31.164:8003",
        #     "192.168.31.164:8002",
        #     "192.168.31.164:8001",
        #     "192.168.31.202:8001",
        # ]
        # url = "http://" + random.choice(url_list)
        # randnum = random.randint(1, 100)
        # if randnum <= 20:
        #     url = await cls.get_base_url()
        url = await cls.get_base_url(tag="para_url")
        url = url + get_settings().PARA_URL
        return url

    @classmethod
    async def get_sql_add_url(cls):
        url = await cls.get_base_url()
        url = url + get_settings().SQL_ADD_URL
        return url

    @classmethod
    async def get_sql_add_many_url(cls):
        url = await cls.get_base_url()
        url = url + get_settings().SQL_ADD_MANY_URL
        return url

    @classmethod
    async def get_sql_update_url(cls):
        url = await cls.get_base_url()
        url = url + get_settings().SQL_UPDATE_URL
        return url

    @classmethod
    async def get_sql_update_list_url(cls):
        url = await cls.get_base_url()
        url = url + get_settings().SQL_UPDATE_LIST_URL
        return url

    @classmethod
    async def get_mongo_save_url(cls):
        url = await cls.get_base_url()
        url = url + get_settings().MONGO_SAVE_URL
        return url

    @classmethod
    async def get_mongo_save_etl_url(cls):
        url = await cls.get_base_url()
        url = url + get_settings().MONGO_SAVE_ETL_URL
        return url

    @classmethod
    async def get_select_url(cls):
        url = await cls.get_base_url()
        url = url + get_settings().SELECT_URL
        return url

    @classmethod
    async def get_reset_new_data_url(cls):
        url = await cls.get_base_url()
        url = url + get_settings().RESET_NEW_DATA_URL
        return url

    @classmethod
    async def get_task_url(cls):
        url = await cls.get_base_url()
        url = url + "/showinfo/task/showinfo/tasks"
        return url

    @classmethod
    async def get_err_url(cls):
        url = await cls.get_base_url()
        url = url + "/err_analysis_server/err_analysis/errs_analysis/err_client_except_find"
        return url

    @classmethod
    async def get_etl_remote_meta_url(cls):
        url = get_settings().ETL_REMOTE_META_URL
        return url

    @classmethod
    async def get_etl_remote_meta_batch_url(cls):
        url = get_settings().ETL_REMOTE_META_BATCH_URL
        return url

    @classmethod
    async def get_etl_remote_ref_url(cls):
        url = get_settings().ETL_REMOTE_REF_URL
        return url

    @classmethod
    async def get_etl_remote_ref_batch_url(cls):
        url = get_settings().ETL_REMOTE_REF_BATCH_URL
        return url

    @classmethod
    async def get_etl_remote_fulltext_batch_url(cls):
        url = get_settings().ETL_REMOTE_FULLTEXT_BATCH_URL
        return url

    @classmethod
    async def get_etl_local_do_url(cls):
        url = await cls.get_base_url()
        url = url + get_settings().ETL_LOCAL_DO_URL
        return url

    @classmethod
    async def get_etl_local_do_batch_url(cls):
        # 规则验证和 para_url 使用一样的权重
        url = await cls.get_base_url(tag="para_url")
        url = url + get_settings().ETL_LOCAL_DO_BATCH_URL
        return url

    @classmethod
    async def get_etl_local_do_batch_ref_url(cls):
        # 规则验证和 para_url 使用一样的权重
        url = await cls.get_base_url(tag="para_url")
        url = url + get_settings().ETL_LOCAL_DO_BATCH_REF_URL
        return url

    @classmethod
    async def get_etl_local_validate_url(cls):
        # 规则验证和 para_url 使用一样的权重
        url = await cls.get_base_url(tag="para_url")
        url = url + get_settings().ETL_LOCAL_VALIDATE_URL
        return url

    @classmethod
    async def get_chaoxing_issue_html_url(cls):
        url = await cls.get_base_url()
        url = url + get_settings().CHAOXING_ISSUE_HTML
        return url
